home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / dev / gg / ncurses-5.3.lha / ncurses-5.3 / test / cardfile.c < prev    next >
C/C++ Source or Header  |  2002-10-24  |  12KB  |  535 lines

  1. /****************************************************************************
  2.  * Copyright (c) 1999-2001,2002 Free Software Foundation, Inc.              *
  3.  *                                                                          *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a  *
  5.  * copy of this software and associated documentation files (the            *
  6.  * "Software"), to deal in the Software without restriction, including      *
  7.  * without limitation the rights to use, copy, modify, merge, publish,      *
  8.  * distribute, distribute with modifications, sublicense, and/or sell       *
  9.  * copies of the Software, and to permit persons to whom the Software is    *
  10.  * furnished to do so, subject to the following conditions:                 *
  11.  *                                                                          *
  12.  * The above copyright notice and this permission notice shall be included  *
  13.  * in all copies or substantial portions of the Software.                   *
  14.  *                                                                          *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
  16.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
  18.  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
  21.  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
  22.  *                                                                          *
  23.  * Except as contained in this notice, the name(s) of the above copyright   *
  24.  * holders shall not be used in advertising or otherwise to promote the     *
  25.  * sale, use or other dealings in this Software without prior written       *
  26.  * authorization.                                                           *
  27.  ****************************************************************************/
  28.  
  29. /*
  30.  * Author: Thomas E. Dickey <dickey@clark.net> 1999
  31.  *
  32.  * $Id: cardfile.c,v 1.19 2002/09/01 17:59:48 tom Exp $
  33.  *
  34.  * File format: text beginning in column 1 is a title; other text forms the content.
  35.  */
  36.  
  37. #include <test.priv.h>
  38.  
  39. #if HAVE_FORM_H && HAVE_PANEL_H && HAVE_LIBFORM && HAVE_LIBPANEL
  40.  
  41. #include <form.h>
  42. #include <panel.h>
  43.  
  44. #include <ctype.h>
  45.  
  46. #define VISIBLE_CARDS 10
  47. #define OFFSET_CARD 2
  48.  
  49. #ifndef CTRL
  50. #define CTRL(x)        ((x) & 0x1f)
  51. #endif
  52.  
  53. typedef struct _card {
  54.     struct _card *link;
  55.     PANEL *panel;
  56.     FORM *form;
  57.     char *title;
  58.     char *content;
  59. } CARD;
  60.  
  61. static CARD *all_cards;
  62. static char default_name[] = "cardfile.dat";
  63.  
  64. #if !HAVE_STRDUP
  65. #define strdup my_strdup
  66. static char *
  67. strdup(char *s)
  68. {
  69.     char *p = (char *) malloc(strlen(s) + 1);
  70.     if (p)
  71.     strcpy(p, s);
  72.     return (p);
  73. }
  74. #endif /* not HAVE_STRDUP */
  75.  
  76. static const char *
  77. skip(const char *buffer)
  78. {
  79.     while (isspace(UChar(*buffer)))
  80.     buffer++;
  81.     return buffer;
  82. }
  83.  
  84. static void
  85. trim(char *buffer)
  86. {
  87.     unsigned n = strlen(buffer);
  88.     while (n-- && isspace(UChar(buffer[n])))
  89.     buffer[n] = 0;
  90. }
  91.  
  92. /*******************************************************************************/
  93.  
  94. static CARD *
  95. add_title(const char *title)
  96. {
  97.     CARD *card, *p, *q;
  98.  
  99.     for (p = all_cards, q = 0; p != 0; q = p, p = p->link) {
  100.     int cmp = strcmp(p->title, title);
  101.     if (cmp == 0)
  102.         return p;
  103.     if (cmp > 0)
  104.         break;
  105.     }
  106.  
  107.     card = (CARD *) calloc(1, sizeof(CARD));
  108.     card->title = strdup(title);
  109.     card->content = strdup("");
  110.  
  111.     if (q == 0) {
  112.     card->link = all_cards;
  113.     all_cards = card;
  114.     } else {
  115.     card->link = q->link;
  116.     q->link = card;
  117.     }
  118.  
  119.     return card;
  120. }
  121.  
  122. static void
  123. add_content(CARD * card, const char *content)
  124. {
  125.     unsigned total, offset;
  126.  
  127.     content = skip(content);
  128.     if ((total = strlen(content)) != 0) {
  129.     if ((offset = strlen(card->content)) != 0) {
  130.         total += 1 + offset;
  131.         card->content = (char *) realloc(card->content, total + 1);
  132.         strcpy(card->content + offset++, " ");
  133.     } else {
  134.         if (card->content != 0)
  135.         free(card->content);
  136.         card->content = (char *) malloc(total + 1);
  137.     }
  138.     strcpy(card->content + offset, content);
  139.     }
  140. }
  141.  
  142. static CARD *
  143. new_card(void)
  144. {
  145.     CARD *card = add_title("");
  146.     add_content(card, "");
  147.     return card;
  148. }
  149.  
  150. static CARD *
  151. find_card(char *title)
  152. {
  153.     CARD *card;
  154.  
  155.     for (card = all_cards; card != 0; card = card->link)
  156.     if (!strcmp(card->title, title))
  157.         break;
  158.  
  159.     return card;
  160. }
  161.  
  162. static void
  163. read_data(char *fname)
  164. {
  165.     FILE *fp;
  166.     CARD *card = 0;
  167.     char buffer[BUFSIZ];
  168.  
  169.     if ((fp = fopen(fname, "r")) != 0) {
  170.     while (fgets(buffer, sizeof(buffer), fp)) {
  171.         trim(buffer);
  172.         if (isspace(UChar(*buffer))) {
  173.         if (card == 0)
  174.             card = add_title("");
  175.         add_content(card, buffer);
  176.         } else if ((card = find_card(buffer)) == 0) {
  177.         card = add_title(buffer);
  178.         }
  179.     }
  180.     fclose(fp);
  181.     }
  182. }
  183.  
  184. /*******************************************************************************/
  185.  
  186. static void
  187. write_data(const char *fname)
  188. {
  189.     FILE *fp;
  190.     CARD *p = 0;
  191.     int n;
  192.  
  193.     if (!strcmp(fname, default_name))
  194.     fname = "cardfile.out";
  195.  
  196.     if ((fp = fopen(fname, "w")) != 0) {
  197.     for (p = all_cards; p != 0; p = p->link) {
  198.         FIELD **f = form_fields(p->form);
  199.         for (n = 0; f[n] != 0; n++) {
  200.         char *s = field_buffer(f[n], 0);
  201.         if (s != 0
  202.             && (s = strdup(s)) != 0) {
  203.             trim(s);
  204.             fprintf(fp, "%s%s\n", n ? "\t" : "", s);
  205.             free(s);
  206.         }
  207.         }
  208.     }
  209.     fclose(fp);
  210.     }
  211. }
  212.  
  213. /*******************************************************************************/
  214.  
  215. /*
  216.  * Count the cards
  217.  */
  218. static int
  219. count_cards(void)
  220. {
  221.     CARD *p;
  222.     int count = 0;
  223.  
  224.     for (p = all_cards; p != 0; p = p->link)
  225.     count++;
  226.  
  227.     return count;
  228. }
  229.  
  230. /*
  231.  * Shuffle the panels to keep them in a natural hierarchy.
  232.  */
  233. static void
  234. order_cards(CARD * first, int depth)
  235. {
  236.     if (first) {
  237.     if (depth && first->link)
  238.         order_cards(first->link, depth - 1);
  239.     top_panel(first->panel);
  240.     }
  241. }
  242.  
  243. /*
  244.  * Return the next card in the list
  245.  */
  246. static CARD *
  247. next_card(CARD * now)
  248. {
  249.     if (now->link)
  250.     now = now->link;
  251.     return now;
  252. }
  253.  
  254. /*
  255.  * Return the previous card in the list
  256.  */
  257. static CARD *
  258. prev_card(CARD * now)
  259. {
  260.     CARD *p;
  261.     for (p = all_cards; p != 0; p = p->link)
  262.     if (p->link == now)
  263.         return p;
  264.     return now;
  265. }
  266.  
  267. /*******************************************************************************/
  268.  
  269. static int
  270. form_virtualize(WINDOW *w)
  271. {
  272.     int c = wgetch(w);
  273.  
  274.     switch (c) {
  275.     case CTRL('W'):
  276.     return (MAX_FORM_COMMAND + 4);
  277.     case CTRL('N'):
  278.     return (MAX_FORM_COMMAND + 3);
  279.     case CTRL('P'):
  280.     return (MAX_FORM_COMMAND + 2);
  281.     case CTRL('Q'):
  282.     case 033:
  283.     return (MAX_FORM_COMMAND + 1);
  284.  
  285.     case KEY_BACKSPACE:
  286.     return (REQ_DEL_PREV);
  287.     case KEY_DC:
  288.     return (REQ_DEL_CHAR);
  289.     case KEY_LEFT:
  290.     return (REQ_LEFT_CHAR);
  291.     case KEY_RIGHT:
  292.     return (REQ_RIGHT_CHAR);
  293.  
  294.     case KEY_DOWN:
  295.     case KEY_NEXT:
  296.     return (REQ_NEXT_FIELD);
  297.     case KEY_UP:
  298.     case KEY_PREVIOUS:
  299.     return (REQ_PREV_FIELD);
  300.  
  301.     default:
  302.     return (c);
  303.     }
  304. }
  305.  
  306. static FIELD **
  307. make_fields(CARD * p, int form_high, int form_wide)
  308. {
  309.     FIELD **f = (FIELD **) calloc(3, sizeof(FIELD *));
  310.  
  311.     f[0] = new_field(1, form_wide, 0, 0, 0, 0);
  312.     set_field_back(f[0], A_REVERSE);
  313.     set_field_buffer(f[0], 0, p->title);
  314.  
  315.     f[1] = new_field(form_high - 1, form_wide, 1, 0, 0, 0);
  316.     set_field_buffer(f[1], 0, p->content);
  317.     set_field_just(f[1], JUSTIFY_LEFT);
  318.  
  319.     f[2] = 0;
  320.     return f;
  321. }
  322.  
  323. static void
  324. show_legend(void)
  325. {
  326.     erase();
  327.     move(LINES - 3, 0);
  328.     addstr("^Q/ESC -- exit form            ^W   -- writes data to file\n");
  329.     addstr("^N   -- go to next card        ^P   -- go to previous card\n");
  330.     addstr("Arrow keys move left/right within a field, up/down between fields");
  331. }
  332.  
  333. #if (defined(KEY_RESIZE) && HAVE_WRESIZE) || NO_LEAKS
  334. static void
  335. free_form_fields(FIELD ** f)
  336. {
  337.     int n;
  338.  
  339.     for (n = 0; f[n] != 0; ++n) {
  340.     free_field(f[n]);
  341.     }
  342.     free(f);
  343. }
  344. #endif
  345.  
  346. /*******************************************************************************/
  347.  
  348. static void
  349. cardfile(char *fname)
  350. {
  351.     WINDOW *win;
  352.     CARD *p;
  353.     CARD *top_card;
  354.     int visible_cards = count_cards();
  355.     int panel_wide = COLS - (visible_cards * OFFSET_CARD);
  356.     int panel_high = LINES - (visible_cards * OFFSET_CARD) - 5;
  357.     int form_wide = panel_wide - 2;
  358.     int form_high = panel_high - 2;
  359.     int y = (visible_cards - 1) * OFFSET_CARD;
  360.     int x = 0;
  361.     int ch = ERR;
  362.     int last_ch;
  363.     int finished = FALSE;
  364.  
  365.     show_legend();
  366.  
  367.     /* make a panel for each CARD */
  368.     for (p = all_cards; p != 0; p = p->link) {
  369.  
  370.     win = newwin(panel_high, panel_wide, y, x);
  371.     keypad(win, TRUE);
  372.     p->panel = new_panel(win);
  373.     box(win, 0, 0);
  374.  
  375.     p->form = new_form(make_fields(p, form_high, form_wide));
  376.     set_form_win(p->form, win);
  377.     set_form_sub(p->form, derwin(win, form_high, form_wide, 1, 1));
  378.     post_form(p->form);
  379.  
  380.     y -= OFFSET_CARD;
  381.     x += OFFSET_CARD;
  382.     }
  383.  
  384.     order_cards(top_card = all_cards, visible_cards);
  385.  
  386.     while (!finished) {
  387.     update_panels();
  388.     doupdate();
  389.  
  390.     last_ch = ch;
  391.     ch = form_virtualize(panel_window(top_card->panel));
  392.     switch (form_driver(top_card->form, ch)) {
  393.     case E_OK:
  394.         break;
  395.     case E_UNKNOWN_COMMAND:
  396.         switch (ch) {
  397.         case MAX_FORM_COMMAND + 1:
  398.         finished = TRUE;
  399.         break;
  400.         case MAX_FORM_COMMAND + 2:
  401.         top_card = prev_card(top_card);
  402.         order_cards(top_card, visible_cards);
  403.         break;
  404.         case MAX_FORM_COMMAND + 3:
  405.         top_card = next_card(top_card);
  406.         order_cards(top_card, visible_cards);
  407.         break;
  408.         case MAX_FORM_COMMAND + 4:
  409.         write_data(fname);
  410.         break;
  411. #if defined(KEY_RESIZE) && HAVE_WRESIZE
  412.         case KEY_RESIZE:
  413.         /* resizeterm already did "something" reasonable, but it cannot
  414.          * know much about layout.  So let's make it nicer.
  415.          */
  416.         panel_wide = COLS - (visible_cards * OFFSET_CARD);
  417.         panel_high = LINES - (visible_cards * OFFSET_CARD) - 5;
  418.  
  419.         form_wide = panel_wide - 2;
  420.         form_high = panel_high - 2;
  421.  
  422.         y = (visible_cards - 1) * OFFSET_CARD;
  423.         x = 0;
  424.  
  425.         show_legend();
  426.         for (p = all_cards; p != 0; p = p->link) {
  427.             FIELD **oldf = form_fields(p->form);
  428.             WINDOW *olds = form_sub(p->form);
  429.  
  430.             win = form_win(p->form);
  431.  
  432.             /* move and resize the card as needed
  433.              * FIXME: if the windows are shrunk too much, this won't do
  434.              */
  435.             mvwin(win, y, x);
  436.             wresize(win, panel_high, panel_wide);
  437.  
  438.             /* reconstruct each form.  Forms are not resizable, and
  439.              * there appears to be no good way to reload the text in
  440.              * a resized window.
  441.              */
  442.             werase(win);
  443.  
  444.             unpost_form(p->form);
  445.             free_form(p->form);
  446.  
  447.             p->form = new_form(make_fields(p, form_high, form_wide));
  448.             set_form_win(p->form, win);
  449.             set_form_sub(p->form, derwin(win, form_high, form_wide,
  450.                          1, 1));
  451.             post_form(p->form);
  452.  
  453.             free_form_fields(oldf);
  454.             delwin(olds);
  455.  
  456.             box(win, 0, 0);
  457.  
  458.             y -= OFFSET_CARD;
  459.             x += OFFSET_CARD;
  460.         }
  461.         break;
  462. #endif
  463.         default:
  464.         beep();
  465.         break;
  466.         }
  467.         break;
  468.     default:
  469.         flash();
  470.         break;
  471.     }
  472.     }
  473. #if NO_LEAKS
  474.     while (all_cards != 0) {
  475.     FIELD **f;
  476.     int count;
  477.  
  478.     p = all_cards;
  479.     all_cards = all_cards->link;
  480.  
  481.     f = form_fields(p->form);
  482.     count = field_count(p->form);
  483.  
  484.     unpost_form(p->form);    /* ...so we can free it */
  485.     free_form(p->form);    /* this also disconnects the fields */
  486.  
  487.     free_form_fields(f);
  488.  
  489.     del_panel(p->panel);
  490.     free(p->title);
  491.     free(p->content);
  492.     free(p);
  493.     }
  494. #endif
  495. }
  496.  
  497. /*******************************************************************************/
  498.  
  499. int
  500. main(int argc, char *argv[])
  501. {
  502.     int n;
  503.  
  504.     setlocale(LC_ALL, "");
  505.  
  506.     initscr();
  507.     cbreak();
  508.     noecho();
  509.  
  510.     if (argc > 1) {
  511.     for (n = 1; n < argc; n++)
  512.         read_data(argv[n]);
  513.     if (count_cards() == 0)
  514.         new_card();
  515.     cardfile(argv[1]);
  516.     } else {
  517.     read_data(default_name);
  518.     if (count_cards() == 0)
  519.         new_card();
  520.     cardfile(default_name);
  521.     }
  522.  
  523.     endwin();
  524.  
  525.     ExitProgram(EXIT_SUCCESS);
  526. }
  527. #else
  528. int
  529. main(void)
  530. {
  531.     printf("This program requires the curses form and panel libraries\n");
  532.     ExitProgram(EXIT_FAILURE);
  533. }
  534. #endif
  535.